// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//

#include <cantor/unresolved/stmts/type_stmt.h>
#include <cantor/unresolved/clause/constant_expr.h>
#include <cantor/unresolved/ddls/enum_element.h>
#include <cantor/unresolved/clause/named_type.h>
#include <cantor/unresolved/clause/type_name_uri.h>

namespace cantor::unresolved {

    UnresolvedConstExpr UnresolvedTypeStmt::type_mod(const size_t idx) const {
        KCHECK(idx < type_mods());
        return UnresolvedConstExpr(instance.type_mods().at(idx));
    }

    int64_t UnresolvedTypeStmt::dimension(const size_t idx) const {
        KCHECK(idx < dimension_size());
        UnresolvedConstExpr dim(instance.array_bounds().at(idx));
        return dim.as_integer();
    }

    std::vector<int64_t> UnresolvedTypeStmt::dimensions() const {
        std::vector<int64_t> result;
        for (size_t i = 0; i < dimension_size(); ++i) {
            result.push_back(dimension(i));
        }
        return result;
    }

    std::string_view UnresolvedTypeStmt::proto_uri() const {
        KCHECK(is_proto());
        UnresolvedConstExpr uri(instance.proto_arg().uri());
        return uri.as_string();
    }

    UnresolvedEnumElement UnresolvedTypeStmt::enum_element(size_t index) const {
        KCHECK(is_union());
        KCHECK(index < instance.enum_arg().element_size());
        auto &ele = instance.enum_arg().element(index);

        return UnresolvedEnumElement(ele);
    }

    std::vector<UnresolvedEnumElement> UnresolvedTypeStmt::enum_elements() const {
        KCHECK(is_union());
        std::vector<UnresolvedEnumElement> result;
        for (size_t i = 0; i < instance.enum_arg().element_size(); ++i) {
            auto &ele = instance.enum_arg().element(i);
            result.push_back(UnresolvedEnumElement(ele));
        }
        return result;
    }

    UnresolvedTypeNameUri UnresolvedTypeStmt::enum_uri() const {
       return  UnresolvedTypeNameUri{instance.enum_arg().uri()};
    }

    std::vector<UnresolvedNamedType> UnresolvedTypeStmt::union_fields() const {
        KCHECK(is_union());
        std::vector<UnresolvedNamedType> result;
        for (size_t i = 0; i < instance.union_arg().types_size(); ++i) {
            result.push_back(UnresolvedNamedType(instance.union_arg().types(i)));
        }
        return result;
    }

    UnresolvedNamedType UnresolvedTypeStmt::union_field(size_t index) const {
        KCHECK(is_union());
        KCHECK(index < instance.union_arg().types_size());

        return UnresolvedNamedType(instance.union_arg().types(index));
    }

    std::vector<UnresolvedNamedType> UnresolvedTypeStmt::struct_fields() const {
        KCHECK(is_struct());
        std::vector<UnresolvedNamedType> result;
        for (size_t i = 0; i < instance.struct_arg().types_size(); ++i) {
            result.push_back(UnresolvedNamedType(instance.struct_arg().types(i)));
        }
        return result;
    }

    UnresolvedNamedType UnresolvedTypeStmt::struct_field(size_t index) const {
        KCHECK(is_struct());
        KCHECK(index < instance.union_arg().types_size());

        return UnresolvedNamedType(instance.struct_arg().types(index));
    }

}  // namespace cantor::unresolved
